package main

import "fmt"

// main
//
//	@Description: 构造者模式：指导者--使用某个构造者--创建某个产品，(用于复杂对象的构建)
func main() {
	//创建一个构造者A
	builderA := NewBuilderA()
	//创建一个指导者
	director := NewDirector(builderA)
	//指导者--指导-->构建者进行产品构建
	product := director.MakeProduct("part1", "part2", "part3")
	fmt.Println(*product)
	//------------------
	//创建一个构造者B
	builderB := NewBuilderB()
	//创建一个指导者
	director = NewDirector(builderB)
	//指导者--指导-->构建者进行产品构建
	product = director.MakeProduct("part1", "part2", "part3")
	fmt.Println(*product)
}

type Product struct {
	Part1 string
	Part2 string
	Part3 string
}

// Director
// @Description: 指导者
type Director struct {
	builder Builder
}

// NewDirector
//
//	@Description: 指导者-构造函数
//	@param builder
//	@return *Director
func NewDirector(builder Builder) *Director {
	return &Director{
		builder: builder,
	}
}

// MakeProduct
//
//	@Description: 指导者--指导-->构建者进行产品构建
//	@receiver d
//	@param pt1
//	@param pt2
//	@param pt3
//	@return *Product
func (d *Director) MakeProduct(pt1 string, pt2 string, pt3 string) *Product {
	d.builder.Part1(pt1)
	d.builder.Part2(pt2)
	d.builder.Part3(pt3)
	return d.builder.Build()
}

// Builder
// @Description: 定义创建复杂对象的[构建者接口]
type Builder interface {
	Part1(pt1 string)
	Part2(pt2 string)
	Part3(pt3 string)
	Build() *Product
}

// BuilderA
// @Description: 实现Builder
type BuilderA struct {
	product *Product
}

// NewBuilderA
//
//	@Description: 构建者A-构造函数
//	@return *BuilderA
func NewBuilderA() *BuilderA {
	return &BuilderA{
		product: &Product{},
	}
}

func (b *BuilderA) Part1(pt1 string) {
	b.product.Part1 = pt1 + "-A"
}

func (b *BuilderA) Part2(pt2 string) {
	b.product.Part2 = pt2 + "-A"
}

func (b *BuilderA) Part3(pt3 string) {
	b.product.Part3 = pt3 + "-A"
}

func (b *BuilderA) Build() *Product {
	return b.product
}

// BuilderB
// @Description: 实现Builder
type BuilderB struct {
	product *Product
}

// NewBuilderB
//
//	@Description: 构建者B-构造函数
//	@return *BuilderB
func NewBuilderB() *BuilderB {
	return &BuilderB{
		product: &Product{},
	}
}

func (b *BuilderB) Part1(pt1 string) {
	b.product.Part1 = pt1 + "-b"
}

func (b *BuilderB) Part2(pt2 string) {
	b.product.Part2 = pt2 + "-b"
}

func (b *BuilderB) Part3(pt3 string) {
	b.product.Part3 = pt3 + "-b"
}

func (b *BuilderB) Build() *Product {
	return b.product
}
